﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using InkFx.WinControl.Core;
using InkFx.WinControl.Utils;
using DA = Temp_20190707_AForm.DockAlignment;
using DTGS = Temp_20190707_AForm.DockTabGroupState;

namespace Temp_20190707_AForm
{
    public class DockPanel : System.Windows.Forms.UserControl
    {
        public DockPanel()
        {
            SetStyle(Win32API.ControlStylesUAORSD, true); 
            base.BackColor = Color.Transparent;
            if (!DesignMode)
            {
                m_CenterPanel = new DockPanelCenter(this);
                m_CenterPanel.Parent = this;
                m_MenuStrip = new ContextMenuStrip();
                m_MenuStrip.ItemClicked += MenuStrip_ItemClicked;
            }
        }


        private DockTabGroup m_ActiveTabGroup = null;
        private DockPanelCenter m_CenterPanel = null;
        private ContextMenuStrip m_MenuStrip = null;
        private List<DockTabGroup> m_ListTabGroup = new List<DockTabGroup>();
        public DockPanelCenter CenterPanel
        {
            get { return m_CenterPanel; }
        }
        public List<DockTabGroup> ListTabGroup
        {
            get
            {
                m_ListTabGroup.RemoveAll(x => x.DockPanel != this || x.Disposing || x.IsDisposed);
                return m_ListTabGroup;
            }
        }
        public Rectangle RectDockInner
        {
            get
            {
                var size = this.Size;
                var padding = this.Padding;
                return new Rectangle(padding.Left, padding.Top, size.Width - padding.Left - padding.Right, size.Height - padding.Top - padding.Bottom);
            }
        }
        public DockTabGroup ActiveTabGroup
        {
            get { return m_ActiveTabGroup; }
            set
            {
                var oldActiveGroup = m_ActiveTabGroup;
                m_ActiveTabGroup = value;
                if (oldActiveGroup != null) { oldActiveGroup.ResetRect(); oldActiveGroup.Invalidate(); }
                if (m_ActiveTabGroup != null) { m_ActiveTabGroup.ResetRect(); m_ActiveTabGroup.Invalidate(); }
                if (m_ActiveTabGroup != null && !m_ActiveTabGroup.ContainsFocus) m_ActiveTabGroup.Focus();
            }
        }


        public DockTabGroup FindTabGroup(SplitterPanel panel)
        {
            var group = this.m_ListTabGroup.Find(x => x.ParentSplitPanel == panel);
            return group;
        }
        public Control FindTabGroupOrSplitControl(SplitterPanel panel, out bool hide)
        {
            hide = false;
            var ctrls = panel.Controls;
            if (ctrls != null && ctrls.Count >= 1)
                foreach (Control ctrl in ctrls)
                {
                    if (ctrl is DockPanelCenter) { hide = false; return ctrl; }
                    if (ctrl is DockSplitControl) { hide = ((DockSplitControl)ctrl).PanelAllCollapsed; return ctrl; }
                    if (ctrl is DockTabGroup) { hide = ((DockTabGroup)ctrl).State != DTGS.Expand; if (!hide) { ctrl.Visible = true; } return ctrl; }
                }

            hide = true;
            var group = FindTabGroup(panel);
            if (group != null) return group;
            return null;
        }


        public DockTabGroup DoDock(ScrollableControl ctrl, DA align)
        {
            return DoDock(ctrl, align, DTGS.Expand);
        }
        public DockTabGroup DoDock(ScrollableControl ctrl, DA align, DTGS state)
        {
            DockTabGroup group = new DockTabGroup(this, null, align);
            ctrl.Dock = DockStyle.Fill;
            group.AppendTabPage(null, "测试面板", ctrl);

            if (state == DTGS.Float)
            {
                DockFloatForm.ShowControl(this, group, Rectangle.Empty);
            }
            else
            {
                var group2 = DoDock(group, align);
                group2.Alignment = align;
                group2.State = state;
                return group2;
            }
            return group;
        }
        public DockTabGroup DoDock(DockTabGroup group, DA align)
        {
            var ctrls = this.Controls;
            Control ctrl1 = null;
            foreach (var c in ctrls) { if ((c is DockSplitControl) || (c is DockTabGroup) || (c is DockPanelCenter)) { ctrl1 = (Control)c; break; } }
            if (ctrl1 == null) return null;

            if (align == DA.Center)
            {
                #region  附着到 中央面板

                var centerGroup = m_CenterPanel.FindGroup();
                if (centerGroup != null)
                {
                    return centerGroup.DoDock(group, DA.Center);
                }
                else
                {
                    group.DisposeFloatForm();
                    group.Alignment = align;
                    group.State = DTGS.Expand;
                    group.Parent = m_CenterPanel;
                    group.Focus();
                    return group;
                }

                #endregion
            }
            else
            {
                #region  执行拆分

                group.DisposeFloatForm();
                group.Alignment = align;
                group.State = DTGS.Expand;
                Control ctrl0 = group;

                var parent = ctrl1.Parent;
                var splitCtrl = new DockSplitControl(this);
                splitCtrl.Dock = DockStyle.Fill;
                if (align == DockAlignment.Top || align == DockAlignment.Bottom)
                { splitCtrl.Orientation = Orientation.Horizontal; }
                if (align == DockAlignment.Right || align == DockAlignment.Bottom)
                { var temp = ctrl0; ctrl0 = ctrl1; ctrl1 = temp; }

                ctrl1.Parent = null;
                splitCtrl.Parent = parent;
                splitCtrl.Size = parent.Size;
                ctrl0.Parent = splitCtrl.Panel1;
                ctrl1.Parent = splitCtrl.Panel2;

                group.Focus();
                return group;

                #endregion
            }

        }
        public void DoDock(DockTabGroup group, DockEventArgs e)
        {
            if (group == null || e == null) return;

            #region  在Group上拆分

            if (e.Control != null && e.TipLayout != null)
            {
                this.SuspendLayout();
                e.Control.DoDock(group, e.Alignment);
                this.ResumeLayout(true);
            }

            #endregion

            #region  四边区域扩展

            else if (e.TipArea != null)
            {
                this.SuspendLayout();
                this.DoDock(group, e.TipArea.Align);
                this.ResumeLayout(true);
            }

            #endregion
        }




        /// <summary>
        /// 判断 ctrl 的 子孙控件中, 是否包含 CenterPanel
        /// </summary>
        public bool ContainsCenterPanel(Control ctrl)
        {
            Control parent = this.CenterPanel;
            while (parent != null && !parent.Disposing && !parent.IsDisposed)
            {
                if (parent == ctrl) return true;
                parent = parent.Parent;
            }
            return false;
        }



        #region  布局分析

        //public List<DockAreaInfo> GetAreaInfos()
        //{
        //    const int OFFSET = 6;
        //    const int SIZE = 30;
        //    int width = this.Width;
        //    int height = this.Height;
        //    Rectangle rectT = new Rectangle((width - SIZE) / 2, OFFSET, SIZE, SIZE);
        //    Rectangle rectB = new Rectangle((width - SIZE) / 2, height - SIZE - OFFSET, SIZE, SIZE);
        //    Rectangle rectL = new Rectangle(OFFSET, (height - SIZE) / 2, SIZE, SIZE);
        //    Rectangle rectR = new Rectangle(width - SIZE - OFFSET, (height - SIZE) / 2, SIZE, SIZE);
        //    Rectangle rectC = new Rectangle((width - SIZE) / 2, (height - SIZE) / 2, SIZE, SIZE);


        //    var areaT = new DockAreaInfo(DockAlignment.Top, this) { Rect = rectT };
        //    var areaB = new DockAreaInfo(DockAlignment.Bottom, this) { Rect = rectB };
        //    var areaL = new DockAreaInfo(DockAlignment.Left, this) { Rect = rectL };
        //    var areaR = new DockAreaInfo(DockAlignment.Right, this) { Rect = rectR };
        //    var areaC = new DockAreaInfo(DockAlignment.Center, this) { Rect = rectC };
        //    var list = new List<DockAreaInfo> { areaT, areaB, areaL, areaR };
        //    if (m_CenterPanel != null && m_CenterPanel.Controls.Count <= 0) list.Add(areaC);
        //    return list;
        //}
        //public DockLayoutInfo GetLayoutInfo()
        //{
        //    return GetLayoutInfo(this);
        //}
        //public DockLayoutInfo GetLayoutInfo(Control parent)
        //{
        //    if (parent == null || parent.Controls.Count <= 0) return null;
        //    var ctrl = parent.Controls[0];
        //    if (ctrl == CenterPanel)
        //    {
        //        var centerPanel = CenterPanel;
        //        DockLayoutInfo layout = new DockLayoutInfo(DockLayoutEnum.CenterPanel, centerPanel);
        //        layout.Layout1 = GetLayoutInfo(centerPanel);
        //        layout.Rect = GetRect(ctrl);
        //        return layout;
        //    }
        //    else if (ctrl is DockSplitControl)
        //    {
        //        var spliter = (DockSplitControl)ctrl;
        //        DockLayoutInfo layout = new DockLayoutInfo((spliter.Orientation == Orientation.Horizontal ? DockLayoutEnum.Horizontal : DockLayoutEnum.Vertical), spliter);
        //        layout.Layout1 = GetLayoutInfo(spliter.Panel1);
        //        layout.Layout2 = GetLayoutInfo(spliter.Panel2);
        //        layout.Rect = GetRect(ctrl);
        //        return layout;
        //    }
        //    else if (ctrl is DockTabGroup)
        //    {
        //        DockLayoutInfo layout = new DockLayoutInfo(DockLayoutEnum.TabGroup, (DockTabGroup)ctrl);
        //        layout.Rect = GetRect(ctrl);
        //        return layout;
        //    }

        //    return null;
        //}
        //private Rectangle GetRect(Control ctrl)
        //{
        //    Rectangle rect1 = this.RectangleToScreen(new Rectangle(Point.Empty, this.Size));
        //    Rectangle rect2 = ctrl.RectangleToScreen(new Rectangle(Point.Empty, ctrl.Size));
        //    Rectangle rect3 = new Rectangle(rect2.X - rect1.X, rect2.Y - rect1.Y, rect2.Width, rect2.Height);
        //    return rect3;
        //}

        #endregion


        private const int DOCK_SIZE = 25;
        public void DoLayout()  
        {
            Console.WriteLine("DockPanel.DoLayout()");
            var listGroup = ListTabGroup;
            bool top = listGroup.Find(x => x.Alignment == DockAlignment.Top && (x.State == DTGS.Collapse || x.State == DTGS.Popup)) != null;
            bool bottom = listGroup.Find(x => x.Alignment == DockAlignment.Bottom && (x.State == DTGS.Collapse || x.State == DTGS.Popup)) != null;
            bool left = listGroup.Find(x => x.Alignment == DockAlignment.Left && (x.State == DTGS.Collapse || x.State == DTGS.Popup)) != null;
            bool right = listGroup.Find(x => x.Alignment == DockAlignment.Right && (x.State == DTGS.Collapse || x.State == DTGS.Popup)) != null;

            this.Padding = new Padding((left ? DOCK_SIZE : 0), (top ? DOCK_SIZE : 0), (right ? DOCK_SIZE : 0), (bottom ? DOCK_SIZE : 0));
        }



        #region  重 置 布 局

        public int LayoutSuspendCount { get; private set; }
        public bool IsLayoutSuspended { get { return LayoutSuspendCount >= 1; } }

        public virtual new void SuspendLayout()
        {
            LayoutSuspendCount++;
            base.SuspendLayout();
        }
        public virtual new void ResumeLayout()
        {
            this.ResumeLayout(true);
        }
        public virtual new void ResumeLayout(bool performLayout)
        {
            LayoutSuspendCount--;

            if (LayoutSuspendCount <= 0)
            {
                LayoutSuspendCount = 0;
                ResetLayout();
            }

            base.ResumeLayout(performLayout);
            this.Refresh();
        }

        public void ResetLayout()
        {
            return;
            base.SuspendLayout();
            var ctrls = this.Controls;
            foreach (var ctrl in ctrls)
            {
                if (ctrl is DockPanelCenter) { ((DockPanelCenter)ctrl).ResetLayout(); }
                if (ctrl is DockSplitControl) { ((DockSplitControl)ctrl).ResetLayout(); }
            }
            this.DoLayout();
            base.ResumeLayout(true);
        }

        #endregion


        #region  弹 出 菜 单

        /// <summary>
        /// 执行 右键弹窗菜单, 不建议改写本函数: 建议改写 CreateTabMenuItems(*) 菜单选项函数 和 OoMenuStripClick(*) 菜单执行函数
        /// </summary>
        /// <param name="group">触发菜单的 Group</param>
        /// <param name="page">触发菜单的 Page</param>
        /// <param name="point">触发菜单时, 相对于 Group 的坐标</param>
        /// <param name="items">需要显示的菜单项</param>
        public virtual void OpenMenuStrip(DockTabGroup group, DockTabGroupPage page, Point point, List<DockMenuItem> items)
        {
            if (items == null || items.Count <= 0) return;
            if (m_MenuStrip == null || m_MenuStrip.Disposing || m_MenuStrip.IsDisposed) return;

            m_MenuStrip.Items.Clear();
            foreach (var item1 in items)
            {
                var item2 = new ToolStripMenuItem(item1.Text, item1.Icon);
                item2.Name = item1.Name;
                item2.Enabled = item1.Enabled;
                item2.Tag = new DockMenuItemInfo(group, page, item1);
                m_MenuStrip.Items.Add(item2);
            }

            m_MenuStrip.Show(group, point);
        }

        /// <summary>
        /// 通过指定的 TabGroup, 计算出 该TabGroup 即将显示的 右键菜单选项
        /// </summary>
        public virtual List<DockMenuItem> CreateTabMenuItems(DockTabGroup group, DockTabGroupPage page, bool isRightButton)
        {
            var items = new List<DockMenuItem>();

            if (group.Alignment == DA.Center && !isRightButton)
            {
                foreach (var page2 in group.ListPage)
                {
                    items.Add(new DockMenuItem("DoFocusPage", page2.Text, true, page2));
                }
            }
            else
            {
                items.Add(new DockMenuItem("DoFloat", "浮动", true));
                items.Add(new DockMenuItem("DoExpand", "停靠", true));
                items.Add(new DockMenuItem("DoCollapse", "折叠", true));
                items.Add(new DockMenuItem("DoHide", "隐藏", true));
            }
            return items;
        }

        /// <summary>
        /// 执行菜单选项的单击触发
        /// </summary>
        /// <param name="group">触发菜单的 Group</param>
        /// <param name="page">触发菜单的 Page</param>
        /// <param name="item">触发菜单的 菜单项</param>
        public virtual void OoMenuStripClick(DockTabGroup group, DockTabGroupPage page, DockMenuItem item)
        {
            if (item.Name == "DoFocusPage")
            {
                #region  右键菜单 选中溢出的 Page

                var page2 = item.Tag as DockTabGroupPage;
                if (page2 != null)
                {
                    if (page2.RectRealTitle.Width <= 0) group.SetSelectedFirstPage(page2);
                    else group.SetSelectedPage(page2);
                }

                #endregion
            }
            else if (item.Name == "DoFloat")
            {
                #region  将选中的Group以窗体模式悬浮

                #endregion
            }
            else if (item.Name == "DoExpand")
            {
                #region  展开选中的Group

                #endregion
            }
            else if (item.Name == "DoCollapse")
            {
                #region  折叠选中的Group

                #endregion
            }
            else if (item.Name == "DoHide")
            {
                #region  隐藏选中的Group

                #endregion
            }
        }
        
        
        private void MenuStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            var item1 = e.ClickedItem;
            var info = item1 == null ? null : item1.Tag as DockMenuItemInfo;
            if (info != null) OoMenuStripClick(info.Group, info.Page, info.Item);
        }

        #endregion



        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            this.Invalidate();
        }
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            this.Invalidate();
        }
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            this.Invalidate();
        }
        protected override void OnMouseEnter(EventArgs e)
        {
            base.OnMouseEnter(e);
            this.Invalidate();
        }
        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            this.Invalidate();
        }
        protected override void OnMouseClick(MouseEventArgs e)
        {
            base.OnClick(e);

            if (m_HashRectPage == null || m_HashRectPage.Count <= 0) return;
            Point point1 = Control.MousePosition;
            Point point2 = this.PointToClient(point1);

            Hashtable hash = null;
            lock (m_HashRectPage.SyncRoot) hash = (Hashtable)m_HashRectPage.Clone();

            foreach (var key in hash.Keys)
            {
                var value = hash[key];
                if (!(key is Rectangle) || !(value is DockTabGroupPage)) continue;
                var rect = (Rectangle)key;
                var page = (DockTabGroupPage)value;
                if (page.ParentGroup != null && !page.ParentGroup.Disposing && !page.ParentGroup.IsDisposed && rect.Contains(point2))
                {
                    DockPopPanel.TogglePopGroup(page);
                }
            }
        }


        protected override void OnPaint(PaintEventArgs e)
        {
            //if (m_DrawingSplitter) return;
            base.OnPaint(e);


            Graphics g = e.Graphics;

            var listGroup = ListTabGroup;
            var listTop = listGroup.FindAll(x => x.Alignment == DockAlignment.Top && (x.State == DTGS.Collapse || x.State == DTGS.Popup));
            var listBottom = listGroup.FindAll(x => x.Alignment == DockAlignment.Bottom && (x.State == DTGS.Collapse || x.State == DTGS.Popup));
            var listLeft = listGroup.FindAll(x => x.Alignment == DockAlignment.Left && (x.State == DTGS.Collapse || x.State == DTGS.Popup));
            var listRight = listGroup.FindAll(x => x.Alignment == DockAlignment.Right && (x.State == DTGS.Collapse || x.State == DTGS.Popup));

            lock (m_HashRectPage.SyncRoot) m_HashRectPage.Clear();
            OnPaintRivetedTabGroup(g, DockAlignment.Top, listTop);
            OnPaintRivetedTabGroup(g, DockAlignment.Bottom, listBottom);
            OnPaintRivetedTabGroup(g, DockAlignment.Left, listLeft);
            OnPaintRivetedTabGroup(g, DockAlignment.Right, listRight);

            //if (this.IsSplitMoving)
            //{
            //    //RepaintSplitterRect();
            //    var handle = this.Handle; //Win32API.GetDesktopWindow();
            //    Win32API.DrawSplitHelper(handle, m_RectSplitter);
            //    //this.Invalidate(true);
            //    //this.Refresh();
            //}
        }





        private Hashtable m_HashRectPage =  Hashtable.Synchronized(new Hashtable());
        protected virtual void OnPaintRivetedTabGroup(Graphics g, DockAlignment align, List<DockTabGroup> listGroup)
        {
            if (g == null || align == DockAlignment.None || align == DockAlignment.Center) return;
            if (listGroup == null || listGroup.Count <= 0) return;

            if (align == DockAlignment.Top)
            {
                #region  Top

                int x = this.Padding.Left;
                int y = 0;
                for (int i = 0, len = listGroup.Count; i < len; i++)
                {
                    var group = listGroup[i];
                    foreach (var page in group.ListPage)
                    {
                        var backColor = (page == null || page.Control == null) ? Color.AliceBlue : page.Control.BackColor;
                        Rectangle rect = new Rectangle(x, y, 70, DOCK_SIZE - 3);
                        g.FillRectangle(new SolidBrush(backColor), rect);
                        x = x + rect.Width + 1;
                        lock (m_HashRectPage.SyncRoot) m_HashRectPage[rect] = page;
                    }
                }

                #endregion
            }
            else if (align == DockAlignment.Bottom)
            {
                #region Bottom

                int x = this.Padding.Left;
                int y = this.Height - DOCK_SIZE + 3;
                for (int i = 0, len = listGroup.Count; i < len; i++)
                {
                    var group = listGroup[i];
                    foreach (var page in group.ListPage)
                    {
                        var backColor = (page == null || page.Control == null) ? Color.AliceBlue : page.Control.BackColor;
                        Rectangle rect = new Rectangle(x, y, 70, DOCK_SIZE - 3);
                        g.FillRectangle(new SolidBrush(backColor), rect);
                        x = x + rect.Width + 1;
                        lock (m_HashRectPage.SyncRoot) m_HashRectPage[rect] = page;
                    }
                }

                #endregion
            }
            else if (align == DockAlignment.Left)
            {
                #region Left

                int x = 0;
                int y = this.Padding.Top;
                for (int i = 0, len = listGroup.Count; i < len; i++)
                {
                    var group = listGroup[i];
                    foreach (var page in group.ListPage)
                    {
                        var backColor = (page == null || page.Control == null) ? Color.AliceBlue : page.Control.BackColor;
                        Rectangle rect = new Rectangle(x, y, DOCK_SIZE - 3, 70);
                        g.FillRectangle(new SolidBrush(backColor), rect);
                        y = y + rect.Height + 1;
                        lock (m_HashRectPage.SyncRoot) m_HashRectPage[rect] = page;
                    }
                }

                #endregion
            }
            else if (align == DockAlignment.Right)
            {
                #region Right

                int x = this.Width - DOCK_SIZE + 3;
                int y = this.Padding.Top;
                for (int i = 0, len = listGroup.Count; i < len; i++)
                {
                    var group = listGroup[i];
                    foreach (var page in group.ListPage)
                    {
                        var backColor = (page == null || page.Control == null) ? Color.AliceBlue : page.Control.BackColor;
                        Rectangle rect = new Rectangle(x, y, DOCK_SIZE - 3, 70);
                        g.FillRectangle(new SolidBrush(backColor), rect);
                        y = y + rect.Height + 1;
                        lock (m_HashRectPage.SyncRoot) m_HashRectPage[rect] = page;
                    }
                }

                #endregion
            }
        }


    }


    public class DockPanelCenter : System.Windows.Forms.UserControl
    {
        public DockPanelCenter(DockPanel dockPanel)
        {
            SetStyle(Win32API.ControlStylesUAORSD, true);
            base.BackColor = Color.Transparent;
            base.Dock = DockStyle.Fill;
            this.DockPanel = dockPanel;
        }

        public DockPanel DockPanel { get; private set; }

        public DockTabGroup FindGroup()
        {
            var ctrls = this.Controls;
            if (ctrls.Count <= 0) return null;

            foreach (var ctrl in ctrls)
            {
                if (ctrl is DockTabGroup) { return (DockTabGroup)ctrl; }
                if (ctrl is DockSplitControl)
                {
                    var splitCtrl = (DockSplitControl)ctrl;
                    var group = splitCtrl.FindGroup();
                    if (group != null) return group;
                }
            }
            return null;
        }
        protected override void OnEnter(EventArgs e)
        {
            base.OnEnter(e);
            DockPopPanel.TogglePopGroup(null);
        }

        public void ResetLayout()
        {
            var ctrls = this.Controls;

            foreach (var ctrl in ctrls)
            {
                if (ctrl is DockPanelCenter) { ((DockPanelCenter)ctrl).ResetLayout(); }
                if (ctrl is DockSplitControl) { ((DockSplitControl)ctrl).ResetLayout(); }
            }

            this.DoLayout();
        }
        public void DoLayout()
        {
            if (this.Disposing || this.IsDisposed || this.DockPanel == null) return;
            Console.WriteLine("DockPanelCenter.DoLayout()");
            //好像没啥事要做的
        }
    }


    public class DockLayoutInfo
    {
        public DockLayoutInfo(DockLayoutEnum @enum, DockTabGroup ctrl)
        {
            this.Enum = @enum;
            this.TabGroup = ctrl;
        }
        public DockLayoutInfo(DockLayoutEnum @enum, DockPanelCenter ctrl)
        {
            this.Enum = @enum;
            this.CenterPanel = ctrl;
        }
        public DockLayoutInfo(DockLayoutEnum @enum, DockSplitControl ctrl)
        {
            this.Enum = @enum;
            this.SplitControl = ctrl;
        }

        public DockLayoutEnum Enum { get; set; }
        public Rectangle Rect { get; set; }
        public DockTabGroup TabGroup { get; set; }
        public DockPanelCenter CenterPanel { get; set; }
        public DockSplitControl SplitControl { get; set; }
        public DockLayoutInfo Layout1 { get; set; }
        public DockLayoutInfo Layout2 { get; set; }
        public DockTipGroupRect TipRect
        {
            get
            {
                const int SIZE = 112;
                Rectangle rect1 = this.Rect;
                Rectangle rect2 = new Rectangle(0, 0, SIZE, SIZE);
                if (rect1.Width < rect2.Width || rect1.Height < rect2.Height) return DockTipGroupRect.Empty;
                Rectangle rect3 = new Rectangle((rect1.X) + (rect1.Width - rect2.Width) / 2, (rect1.Y) + (rect1.Height - rect2.Height) / 2, rect2.Width, rect2.Height);
                return new DockTipGroupRect(rect3, !(TabGroup != null && TabGroup.State == DTGS.Expand));
            }
        }
        public DockPanel DockPanel
        {
            get
            {
                if (TabGroup != null && TabGroup.DockPanel != null) return TabGroup.DockPanel;
                if (SplitControl != null && SplitControl.DockPanel != null) return SplitControl.DockPanel;
                return null;
            }
        }


        public bool MouseInRect()
        {
            var ctrl = (TabGroup as Control) ?? (CenterPanel as Control) ?? (SplitControl as Control);
            var point1 = Control.MousePosition;
            var point2 = ctrl.PointToClient(point1);
            return Rect.Contains(point2);
        }
        public DockAlignment MouseInTipRect()
        {
            var ctrl = (TabGroup as Control) ?? (CenterPanel as Control) ?? (SplitControl as Control);
            if (ctrl == null) return DockAlignment.None;
            var point1 = Control.MousePosition;
            var point2 = ctrl.PointToClient(point1);
            return TipRect.Contains(point2);
        }

        public List<DockLayoutInfo> GetTabGroups()
        {
            if (this.Enum == DockLayoutEnum.TabGroup) return new List<DockLayoutInfo> { this };
            else if (this.Enum == DockLayoutEnum.CenterPanel)
            {
                List<DockLayoutInfo> list = new List<DockLayoutInfo>();
                var result1 = Layout1 == null ? null : Layout1.GetTabGroups();
                if (result1 != null) list.AddRange(result1);
                return list;
            }
            else
            {
                List<DockLayoutInfo> list = new List<DockLayoutInfo>();

                var result1 = Layout1 == null ? null : Layout1.GetTabGroups();
                if (result1 != null) list.AddRange(result1);

                var result2 = Layout2 == null ? null : Layout2.GetTabGroups();
                if (result2 != null) list.AddRange(result2);

                return list;
            }
        }
    }

    public class DockAreaInfo
    {
        public DockAreaInfo(DockAlignment align, DockPanel ctrl)
        {
            this.Align = align;
            this.DockPanel = ctrl;
        }

        public DockAlignment Align { get; set; }
        public DockPanel DockPanel { get; set; }
        public Rectangle Rect { get; set; }
        public bool MouseInRect()
        {
            var ctrl = Align == DA.Center ? (this.DockPanel.CenterPanel as Control) : (this.DockPanel as Control); 
            var point1 = Control.MousePosition;
            var point2 = ctrl.PointToClient(point1);
            return Rect.Contains(point2);
        }
        public DockAlignment MouseInTipRect()
        {
            if (MouseInRect()) return Align;
            return DockAlignment.None;
        }
    }


    public struct DockTipGroupRect
    {
        public static readonly DockTipGroupRect Empty = new DockTipGroupRect();

        public DockTipGroupRect(Rectangle rect, bool onlyCenter) : this()
        {
            int swidth = 32;
            int sheight = 32;
            int split = (rect.Width - (swidth * 3)) / 4;

            RectFull = rect;
            RectCenter = new Rectangle(RectFull.X + swidth + (split * 2), RectFull.Y + sheight + (split * 2), swidth, sheight);

            OnlyCenter = onlyCenter;
            if (onlyCenter)
            {
                RectTop = RectBottom = RectLeft = RectRight = Rectangle.Empty;
            }
            else
            {
                RectTop = new Rectangle(RectFull.X + swidth + (split * 2), RectFull.Y + split, swidth, sheight);
                RectBottom = new Rectangle(RectFull.X + swidth + (split * 2), RectFull.Y + (sheight * 2) + (split * 3), swidth, sheight);
                RectLeft = new Rectangle(RectFull.X + split, RectFull.Y + sheight + (split * 2), swidth, sheight);
                RectRight = new Rectangle(RectFull.X + (swidth * 2) + (split * 3), RectFull.Y + sheight + (split * 2), swidth, sheight);
            }
        }

        public bool OnlyCenter { get; set; }
        public Rectangle RectFull { get; set; }
        public Rectangle RectCenter { get; set; }
        public Rectangle RectTop { get; set; }
        public Rectangle RectBottom { get; set; }
        public Rectangle RectLeft { get; set; }
        public Rectangle RectRight { get; set; }

        public int Width { get { return RectFull.Width; } }
        public int Height { get { return RectFull.Height; } }

        public DockAlignment Contains(Point point)
        {
            if(RectCenter.Contains(point)) return DockAlignment.Center;
            if(RectTop.Contains(point)) return DockAlignment.Top;
            if(RectBottom.Contains(point)) return DockAlignment.Bottom;
            if(RectLeft.Contains(point)) return DockAlignment.Left;
            if(RectRight.Contains(point)) return DockAlignment.Right;
            return DockAlignment.None;
        }
    }


    public enum DockLayoutEnum
    {
        CenterPanel,
        TabGroup,
        Vertical,
        Horizontal,
    }

    public enum DockAlignment
    {
        None,
        Top,
        Bottom,
        Left,
        Right,
        Center,
        FloatCenter,
    }

    public class DockEventArgs : EventArgs
    {
        public DockTabGroup Control;
        public DockAreaInfo TipArea;
        public DockLayoutInfo TipLayout;
        public DockAlignment Alignment;
    }

}
